package com.cloud.service.generate;

import com.cloud.model.User;
import com.cloud.service.generate.auto.QClass;
import com.cloud.service.generate.auto.QField;
import com.cloud.service.sys.AppService;
import com.cloud.util.DateUtil;
import com.cloud.util.FileUtils;
import com.cloud.util.FreemarkerUtil;
import com.cloud.util.SysUtil;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;
import javax.persistence.Transient;
import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * V1.0
 * 生成模版代码
 */
public class CodeUtils {
    private static String outFolder = "D:/freemaker/genCode";

    public static void main(String arges[]) throws Exception {
//        genCode();
//        genTest();
        getEnumDesc();
    }

    public static void genCode() {
        generate(User.class, CodeType.FILE);
//        generate(MyAuths.class, CodeType.FRAGMENT);
    }

    public static void generate(Class clazz, CodeType codeEnums) {
        try {
            StackTraceElement[] s = new Exception().getStackTrace();
            String className = s[1].getClassName();
            FileUtils.deleteAllFile(new File(outFolder), false);
            FreemarkerUtil freemarkerUtil = new FreemarkerUtil();
            String ftlFolder = "";
            switch (codeEnums) {
                case FILE:
                    ftlFolder = ClassLoader.getSystemResource("").getPath() + "generate";
                    break;
                case FRAGMENT:
                    ftlFolder = ClassLoader.getSystemResource("").getPath() + "generate/fragment";
                    break;
            }

            if (!CodeUtils.class.getSimpleName().equals(className)) {
                ftlFolder = ftlFolder.replace("test-classes", "classes");
            }
            ftlFolder = ftlFolder.replaceAll("%20", " ");
            freemarkerUtil.setEn(ftlFolder);
            //目录有空格路径替换
            File folder = new File(ftlFolder);
            ModelTemplate modelTemplate = initModelTemplate(clazz);
            if (folder.exists()) {
                switch (codeEnums) {
                    case FILE:
                        genFile(freemarkerUtil, modelTemplate, folder.listFiles());
                        break;
                    case FRAGMENT:
                        genFragment(freemarkerUtil, modelTemplate, folder.listFiles());
                        break;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static void genFile(FreemarkerUtil freemarkerUtil, ModelTemplate modelTemplate, File[] files) throws Exception {
        outFolder += DateUtil.format("yyyyMMddHHmmss", new Date());
        for (File f : files) {
            if (f.isDirectory()) {
                continue;
            }
            String fileName = f.getName().substring(0, f.getName().lastIndexOf("."));
            String destPath = outFolder + File.separator + fileName.toLowerCase() + File.separator + "back" + File.separator + modelTemplate.getClassName() + fileName + ".java";
            if (fileName.startsWith("Page")) {
                destPath = outFolder + File.separator + "_jsp" + File.separator + "back" + File.separator +
                        SysUtil.lowFirst(modelTemplate.getClassName()) + File.separator
                        + SysUtil.lowFirst(fileName.replace("Page", "")) + ".jsp";
            }
            freemarkerUtil.process(f.getName(), destPath, modelTemplate);
        }
        System.out.println("生成成功");
        System.out.println("output folder: " + outFolder);
        java.awt.Desktop.getDesktop().open(new File(outFolder));
    }

    private static void genFragment(FreemarkerUtil freemarkerUtil, ModelTemplate modelTemplate, File[] files) throws Exception {
        for (File f : files) {
            String str = freemarkerUtil.getFileString(f.getName(), modelTemplate);
            System.out.println(str);
        }
    }

    public static void genOne(ModelTemplate modelTemplate, String templateName) throws Exception {
        FreemarkerUtil freemarkerUtil = new FreemarkerUtil();
        String ftlFolder = ClassLoader.getSystemResource("").getPath() + "generate";
        ftlFolder = ftlFolder.replaceAll("%20", " ");
        freemarkerUtil.setEn(ftlFolder);
        String destPath = outFolder + File.separator + "test" + File.separator + modelTemplate.getClassName() + "test" + ".java";
        freemarkerUtil.process(templateName, destPath, modelTemplate);
    }

    public static ModelTemplate initModelTemplate(Class clazz) {
        ModelTemplate modelTemplate = new ModelTemplate();
        int index = clazz.getName().indexOf(".model");
        if (index == -1) {
            System.out.println("can't get the namespace");
        }
        String namespace = clazz.getName().substring(0, index);
        modelTemplate.setNamespace(namespace);
        modelTemplate.setFullClassName(clazz.getName());
        modelTemplate.setClassName(clazz.getSimpleName());
        modelTemplate.setClassNameLowerCase(SysUtil.toLowerCaseFirstOne(clazz.getSimpleName()));
        modelTemplate.setFieldMap(FieldService.getFieldMap(clazz));
        QClass qClass = (QClass) clazz.getAnnotation(QClass.class);
        modelTemplate.setClassZhName(qClass.name());
        return modelTemplate;
    }

    //生成数据库文档
    public static void genDatabaseDoc() {
        List<Class> classes = AppService.getEntities();
        for (Class model : classes) {
            genClassDatabaseDoc(model);
        }
    }

    public static void genClassDatabaseDoc(Class model) {
        QClass qClass = (QClass) model.getAnnotation(QClass.class);
        Table annotation = (Table) model.getAnnotation(Table.class);
        Entity entity = (Entity) model.getAnnotation(Entity.class);
        if (qClass != null && annotation != null && entity != null && StringUtils.isNotEmpty(qClass.name())) {
            String tableName = annotation.name();
            System.out.println(tableName + "\t" + qClass.name());

            Field[] fields = model.getDeclaredFields();
            if (ArrayUtils.isNotEmpty(fields)) {
                for (Field field : fields) {
                    Column columnAnotation = field.getAnnotation(Column.class);
                    QField qFieldAnnotation = field.getAnnotation(QField.class);
                    Transient transientAnno = field.getAnnotation(Transient.class);

                    if (transientAnno == null) {
                        String fieldName = "";
                        if (columnAnotation != null && StringUtils.isNotEmpty(columnAnotation.name())) {
                            fieldName = columnAnotation.name();
                        } else {
                            fieldName = field.getName();
                        }
                        String fieldDesc = "";
                        if (columnAnotation != null && StringUtils.isNotEmpty(columnAnotation.columnDefinition())) {
                            fieldDesc = columnAnotation.columnDefinition();
                            System.out.println("\t" + fieldName + "\t" + fieldDesc);
                            continue;
                        } else if (qFieldAnnotation != null && StringUtils.isNotEmpty(qFieldAnnotation.name())) {
                            fieldDesc = qFieldAnnotation.name();
                        } else {
                            fieldDesc = field.getName();
                        }
                        System.out.println("\t" + fieldName + "\t" + CodeTemplateUtil.transferJavaFiled2MysqlField(field.getType().getSimpleName(), fieldDesc) + "\t" + fieldDesc);
                    }
                }
            }
            System.out.println("\t`id` varchar(50) COMMENT '主键id',\n" +
                    "\t`version` bigint(20) DEFAULT COMMENT '版本,\n" +
                    "\t`create_time` datetime COMMENT '创建时间,\n" +
                    "\t`creator` varchar(50) COMMENT '创建人,\n" +
                    "\t`modifier` varchar(50) COMMENT '修改人,\n" +
                    "\t`modify_time` datetime COMMENT '修改时间,");
            System.out.println();
        }
    }

    public static Map<String, String> getEnumDesc() {
        Map<String, String> map = new HashMap<>();
        try {

            List<Class> classes = AppService.getEntities();
            for (Class model : classes) {
                //这里是获得枚举的遍历方法  即:枚举对象.values();一样      
                Method method = null;
                try {
                    method = model.getMethod("values");

                    //这里获取所有的枚举对象 method.invoke(null)也可写成method.invoke(null,null)
                    Object[] inter = (Object[]) method.invoke(null);
                    String desc = "";
                    Object[] objs = new Object[0];
                    for (Object enumMessage : inter) {
                        Method name = model.getMethod("name");
//                    System.out.println(name.invoke(enumMessage, null));
                        Object nameVal = name.invoke(enumMessage, objs);
                        Method getName = model.getMethod("getName");
//                    System.out.println(getName.invoke(enumMessage, null));
                        Object getNameVal = getName.invoke(enumMessage, objs);
                        desc += nameVal + " : " + getNameVal;
                    }
                    map.put(model.getSimpleName(), desc);
                } catch (Exception e) {
                    //
                }
            }

        } catch (Exception e) {
            //e.printStackTrace();
        }
        return map;
    }
}
